package com.lp.chapter001.handler.easypoi;

import cn.afterturn.easypoi.handler.inter.IReadHandler;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.IdUtil;
import com.lp.chapter001.entity.Student;
import com.lp.chapter001.excel.easypoi.EasypoiImportExcel;
import com.lp.chapter001.mapper.StudentMapper;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * easypoi导入
 * @author LP to 2024/03/01
 */
@Slf4j
@Service
@Scope("prototype")
public class EasypoiStudentImportHandler implements IReadHandler<EasypoiImportExcel> {
    /** 成功数据集合 */
    private final CopyOnWriteArrayList<EasypoiImportExcel> successList = new CopyOnWriteArrayList<>();
    /** 失败数据集合 */
    private final CopyOnWriteArrayList<EasypoiImportExcel> failList = new CopyOnWriteArrayList<>();
    /** 批处理条数 */
    private final static int BATCH_COUNT = 20000;
    @Resource
    private ThreadPoolExecutor easypoiStudentImportThreadPool;
    @Resource
    private StudentMapper studentMapper;

    /**
     * 解析数据
     * @author Liupeng to 2024/3/1
     */
    @Override
    public void handler(EasypoiImportExcel importExcel) {
        // 参数校验
        if (StringUtils.isBlank(importExcel.getName())) {
            importExcel.setErrorMsg("学生名称不能为空");
            failList.add(importExcel);
            return;
        }
        successList.add(importExcel);
        if (successList.size() >= BATCH_COUNT) {
            saveDate();
        }
    }

    /**
     * 处理完成所有数据之后调用
     * @author Liupeng to 2024/3/1
     */
    @Override
    public void doAfterAll() {
        saveDate();
    }

    /**
     * 保存信息
     * @author Liupeng to 2024/3/1
     */
    private void saveDate() {
        // 拆分list，每个list 2000 条数据
        List<List<EasypoiImportExcel>> lists = ListUtil.split(successList, 1000);
        final CountDownLatch countDownLatch = new CountDownLatch(lists.size());
        for (List<EasypoiImportExcel> list : lists) {
            easypoiStudentImportThreadPool.execute(() -> {
                try {
                    studentMapper.insertBatch(list.stream().map(o -> {
                        Student student = new Student();
                        student.setNo(IdUtil.getSnowflakeNextId());
                        student.setName(o.getName());
                        student.setStudentNum(o.getStudentNum());
                        student.setAge(o.getAge());
                        student.setSex(o.getSex());
                        student.setBirthday(o.getBirthday());
                        return student;
                    }).collect(Collectors.toList()));
                } catch (Exception e) {
                    log.error("启动线程失败,e:{}", e.getMessage(), e);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        // 等待所有线程执行完
        try {
            countDownLatch.await();
        } catch (Exception e) {
            log.error("等待所有线程执行完异常,e:{}", e.getMessage(), e);
        }
        // 提前将不再使用的集合清空，释放资源
        successList.clear();
        failList.clear();
        lists.clear();
    }
}
